home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
System Booster
/
System Booster.iso
/
Archives
/
ForCLI
/
MComms_1_4.lha
/
Src
/
clickstart.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-08-31
|
9KB
|
306 lines
/*
** clickstart.c - enable/disable features of AmigaDOS
** Copyright © 1994-95 Michael Letowski
*/
#define __USE_SYSBASE
#define ECS_SPECIFIC /* Enable hardware */
#include <exec/types.h>
#include <exec/execbase.h>
#include <dos/rdargs.h>
#include <dos/var.h>
#include <devices/trackdisk.h>
#include <graphics/gfxbase.h>
#include <hardware/custom.h>
#include <support/types.h>
#include <support/exec.h>
#include <support/dos.h>
#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/intuition.h>
#include "clickstart.rev.h"
#define DOS_NAME "dos.library"
#define DOS_VERN 37L
#define GFX_NAME "graphics.library"
#define GFX_VERN 39L
#define INT_NAME "intuition.library"
#define INT_VERN 0L
#define TRACK_NAME "trackdisk.device"
/* Args template */
#define TEMPLATE "CLICK/S,NOCLICK/S,STAR/S,NOSTAR/S,"\
"PIPE/K,NOPIPE/S,MULTI/K,NOMULTI/S,"\
"BORBLANK/S,NOBORBLANK/S,BORSPRITES/S,NOBORSPRITES/S,"\
"ALERT/K/N,RETRY/K/N,QUANTUM/K/N,QUIET/S"
/* Info message */
#define MSG_STATUS "System state:\n"\
"\tClick is %s\n"\
"\tStar is %s\n"\
"\tPipe char is %s\n"\
"\tMulti command char is %s\n"\
"\tBorder blank is %s\n"\
"\tBorder sprites are %s\n"\
"\tAlert lasts %ld frame%s\n"\
"\tNumber of retries is %ld\n"\
"\tDispatch quantum is %ld frame%s\n"
/* Pipe enable/disable */
#define PIPE_VAR_NAME "_pchar"
/* Multi command enable/disable */
#define MULTI_VAR_NAME "_mchar"
#define VAR_LEN 1
#define VAR_FLAGS (LV_VAR | GVF_LOCAL_ONLY)
#define VAR_SIZE (VAR_LEN+3)
/* Default pipe and multi characters */
#define DEF_PIPE "|"
#define DEF_MULTI "\\"
/* On/off texts */
#define ON "ON"
#define OFF "OFF"
#define UNKNOWN "?"
/* Ranges */
#define MIN_RETRY 0
#define MAX_RETRY 255
#define MIN_ALERT 0
#define MAX_ALERT 0x7FFFFFFF
#define MIN_QUANT 1
#define MAX_QUANT 65535
#define PStr(arg,def) (*(arg)=='\0' ? (def) : (arg))
STATIC CONST TEXT VersionString[]=
VERSION(PROG_NAME,PROG_VERSION,PROG_REVISION,PROG_DATE);
struct Options
{
LONG opt_Click; /* C=CLICK/S */
LONG opt_NoClick; /* NC=NOCLICK/S */
LONG opt_Star; /* S=STAR/S */
LONG opt_NoStar; /* NS=NOSTAR/S */
STRPTR opt_Pipe; /* P=PIPE/K */
LONG opt_NoPipe; /* NP=NOPIPE/S */
STRPTR opt_Multi; /* M=MULTI/S */
LONG opt_NoMulti; /* NM=NOMULTI/S */
LONG opt_Blank; /* BB=BORBLANK/S */
LONG opt_NoBlank; /* NBB=NOBORBLANK/S */
LONG opt_Sprites; /* BS=BORSPRITES */
LONG opt_NoSprites; /* NBS=NOBORSPRITES */
LONG *opt_Alert; /* A=ALERT/K/N */
LONG *opt_Retry; /* R=RETRY/K/N */
LONG *opt_Quant; /* Q=QUANTUM/K/N */
LONG opt_Quiet; /* QUIET/S */
}; /* Options */
struct States
{
STRPTR state_Click;
STRPTR state_Star;
STRPTR state_Pipe;
STRPTR state_Multi;
STRPTR state_Blank;
STRPTR state_Sprites;
LONG state_Alert;
STRPTR state_AlertS;
LONG state_Retry;
LONG state_Quant;
STRPTR state_QuantS;
}; /* States */
STATIC VOID HandleTrackDisk(struct Options *opts, struct States *stat, LONG *error);
STATIC VOID HandleVar(STRPTR varName, STRPTR varVal, STRPTR defVal, LONG off,
LONG *error, STRPTR *result, struct DosLibrary *DOSBase);
STATIC VOID HandleBorder(struct Options *opts, struct States *stat, LONG *error,
struct DosLibrary *DOSBase);
LONG ClickStart(VOID)
{
struct ExecBase *SysBase=*((struct ExecBase **)4);
struct DosLibrary *DOSBase;
CHAR PipeVal[VAR_SIZE],MultiVal[VAR_SIZE];
struct Options Opts;
struct States Stat;
struct RDArgs *Args;
LONG *DOSFlags,RC=RETURN_FAIL;
/* Open DOS */
unless(DOSBase=(struct DosLibrary *)OpenLibrary(DOS_NAME,DOS_VERN))
throw2(SetResult2(ERROR_INVALID_RESIDENT_LIBRARY), NO_DOS);
/* Read arguments */
clear(&Opts); /* Clear out buffer */
unless(Args=ReadArgs(TEMPLATE,(LONG *)&Opts,NULL))
throw2(PrintFault(IoErr(),PROG_NAME), NO_ARGS);
/* Check args */
if(Opts.opt_Click && Opts.opt_NoClick || Opts.opt_Star && Opts.opt_NoStar ||
Opts.opt_Pipe && Opts.opt_NoPipe || Opts.opt_Multi && Opts.opt_NoMulti ||
Opts.opt_Blank && Opts.opt_NoBlank || Opts.opt_Sprites && Opts.opt_NoSprites)
throw2(CauseIoErr(ERROR_TOO_MANY_ARGS,PROG_NAME), BAD_ARGS);
/* Make values legal*/
if(Opts.opt_Alert) *Opts.opt_Alert=clamp(*Opts.opt_Alert,MIN_ALERT,MAX_ALERT);
if(Opts.opt_Retry) *Opts.opt_Retry=clamp(*Opts.opt_Retry,MIN_RETRY,MAX_RETRY);
if(Opts.opt_Quant) *Opts.opt_Quant=clamp(*Opts.opt_Quant,MIN_QUANT,MAX_QUANT);
RC=RETURN_ERROR; /* Working a bit */
/* Handle clicking */
HandleTrackDisk(&Opts,&Stat,&RC);
/* Wildstar */
DOSFlags=&DOSBase->dl_Root->rn_Flags;
if(Opts.opt_Star) fset(*DOSFlags,RNF_WILDSTAR);
if(Opts.opt_NoStar) fclr(*DOSFlags,RNF_WILDSTAR);
Stat.state_Star=ftst(*DOSFlags,RNF_WILDSTAR) ? ON : OFF;
/* Piping */
Stat.state_Pipe=PipeVal;
HandleVar(PIPE_VAR_NAME,Opts.opt_Pipe,DEF_PIPE,
Opts.opt_NoPipe,&RC,&Stat.state_Pipe,DOSBase);
/* Multi command execution */
Stat.state_Multi=MultiVal;
HandleVar(MULTI_VAR_NAME,Opts.opt_Multi,DEF_MULTI,
Opts.opt_NoMulti,&RC,&Stat.state_Multi,DOSBase);
/* Border stuff */
HandleBorder(&Opts,&Stat,&RC,DOSBase);
/* Alerts timing */
if(Opts.opt_Alert) SysBase->LastAlert[3]=*Opts.opt_Alert;
Stat.state_Alert=SysBase->LastAlert[3];
Stat.state_AlertS=(Stat.state_Alert==1) ? NULL : "s";
/* Quantum */
if(Opts.opt_Quant) SysBase->Quantum=*Opts.opt_Quant;
Stat.state_Quant=SysBase->Quantum;
Stat.state_QuantS=(Stat.state_Quant==1) ? NULL : "s";
unless(Opts.opt_Quiet)
VPrintf(MSG_STATUS,(LONG *)&Stat);
catch(BAD_ARGS, );
catch(NO_ARGS, FreeArgs(Args));
catch(NO_DOS, CloseLibrary((struct Library *)DOSBase));
return(RC);
} /* ClickStart */
STATIC VOID HandleTrackDisk(struct Options *opts, struct States *stat, LONG *error)
{
struct ExecBase *SysBase=*((struct ExecBase **)4);
struct MsgPort *Port;
struct IOExtTD *IO;
struct TDU_PublicUnit *TDUUnit;
ULONG Unit;
stat->state_Click=UNKNOWN; /* We don't know yet */
try(Port=CreateMsgPort(), NO_PORT);
try(IO=CreateIORequest(Port,sizeof(struct IOExtTD)), NO_IO)
*error=RETURN_OK; /* Everything OK so far */
for(Unit=0; Unit<4; Unit++) /* For each drive */
if(OpenDevice(TRACK_NAME,Unit,(struct IORequest *)IO,0)==0)
{
TDUUnit=(struct TDU_PublicUnit *)IO->iotd_Req.io_Unit;
/* Disable/enable clicking */
if(opts->opt_Click) fclr(TDUUnit->tdu_PubFlags,TDPF_NOCLICK);
if(opts->opt_NoClick) fset(TDUUnit->tdu_PubFlags,TDPF_NOCLICK);
stat->state_Click=ftst(TDUUnit->tdu_PubFlags,TDPF_NOCLICK) ? OFF : ON;
/* Change retry count */
if(opts->opt_Retry) TDUUnit->tdu_RetryCnt=*opts->opt_Retry;
stat->state_Retry=TDUUnit->tdu_RetryCnt;
/* Clean up */
CloseDevice((struct IORequest *)IO);
}
catch(NO_PORT, DeleteMsgPort(Port));
catch(NO_IO, DeleteIORequest(IO));
} /* HandleTrackDisk */
STATIC VOID HandleVar(STRPTR varName, STRPTR varVal, STRPTR defVal, LONG off,
LONG *error, STRPTR *result, struct DosLibrary *DOSBase)
{
STRPTR State=*result;
struct LocalVar *Var;
if(varVal)
unless(SetVar(varName,PStr(varVal,defVal),VAR_LEN,VAR_FLAGS))
{
PrintFault(IoErr(),PROG_NAME);
*error=RETURN_ERROR;
}
if(off)
unless(DeleteVar(varName,VAR_FLAGS))
{
PrintFault(IoErr(),PROG_NAME);
*error=RETURN_ERROR;
}
if(Var=FindVar(varName,VAR_FLAGS)) /* Could find var */
{
State[0]='\''; /* Store its contents */
State[1]=*(Var->lv_Value);
State[2]='\'';
State[3]='\0';
}
else /* Var nor found */
*result=OFF; /* So it's off */
} /* HandleVar */
STATIC VOID HandleBorder(struct Options *opts, struct States *stat, LONG *error,
struct DosLibrary *DOSBase)
{
struct ExecBase *SysBase=*((struct ExecBase **)4);
struct GfxBase *GfxBase;
struct IntuitionBase *IntuitionBase;
UBYTE BP3Bits;
stat->state_Sprites=UNKNOWN;
stat->state_Blank=UNKNOWN;
if(GfxBase=(struct GfxBase *)OpenLibrary(GFX_NAME,GFX_VERN))
{
BP3Bits=GfxBase->BP3Bits; /* Remember flags */
/* Sprites on border */
if(opts->opt_Sprites) fset(GfxBase->BP3Bits,BPLCON3_EXTBLKZD);
if(opts->opt_NoSprites) fclr(GfxBase->BP3Bits,BPLCON3_EXTBLKZD);
stat->state_Sprites=ftst(GfxBase->BP3Bits,BPLCON3_EXTBLKZD) ? ON : OFF;
/* Blank border */
if(opts->opt_Blank) fset(GfxBase->BP3Bits,BPLCON3_BRDNBLNK);
if(opts->opt_NoBlank) fclr(GfxBase->BP3Bits,BPLCON3_BRDNBLNK);
stat->state_Blank=ftst(GfxBase->BP3Bits,BPLCON3_BRDNBLNK) ? ON : OFF;
if(BP3Bits!=GfxBase->BP3Bits) /* Changed something */
if(IntuitionBase=(struct IntuitionBase *)OpenLibrary(INT_NAME,INT_VERN))
{
RemakeDisplay(); /* Make changes visible */
CloseLibrary((struct Library *)IntuitionBase);
}
else /* Unable to open intuition */
*error=RETURN_WARN; /* Just warning */
CloseLibrary((struct Library *)GfxBase); /* Close graphics */
}
else /* No graphics */
{
*error=RETURN_ERROR; /* An error */
CauseIoErr(ERROR_INVALID_RESIDENT_LIBRARY,PROG_NAME);
}
} /* HandleBorder */